@use '@wordpress/base-styles/mixins';
@use '@wordpress/base-styles/variables';
@use '../utils/theme-variables' as theme;

/* Root of the component. */
.calendar {
	// TODO: add font family rule when Theme is ready

	// Internal variables
	--a8c-calendar-outline-focus: 1.5px solid #{theme.$components-color-accent};
	--a8c-calendar-button-height: #{variables.$grid-unit-40};
	--a8c-calendar-button-width: #{variables.$grid-unit-40};
	--a8c-calendar-nav-height: #{variables.$grid-unit-40};

	// TODO: themify / align to DS tokens
	--a8c-calendar-range-middle-background-color: color-mix(in srgb, #{theme.$components-color-accent} 4%, transparent);
	--a8c-calendar-preview-border-color: color-mix(in srgb, #{theme.$components-color-accent} 16%, transparent);

	position: relative; /* Required to position the navigation toolbar. */
	box-sizing: border-box;
	display: inline flow-root;
	color: theme.$components-color-foreground;
	background-color: theme.$components-color-background;
	font-size: variables.$font-size-medium;
	font-weight: variables.$font-weight-regular;
	z-index: 0; // Create a stacking context and render on top of the background.

	*, *::before, *::after {
		box-sizing: border-box;
	}
}

.calendar__day {
	padding: 0;
	position: relative;

	// Setting text color on the day container instead of directly on the
	// day button to ensure that the color of the dot used to indicate today's
	// date follows the same color as the button's text, since the button
	// inherits its text color.
	&:has(.calendar__day-button:disabled) {
		color: theme.$components-color-disabled;
	}
	&:has(.calendar__day-button:hover:not(:disabled)),
	&:has(.calendar__day-button:focus-visible) {
		color: theme.$components-color-accent;
	}
}

.calendar__day-button {
	background: none;
	padding: 0;
	margin: 0;
	cursor: pointer;
	justify-content: center;
	align-items: center;
	display: flex;
	position: relative;

	width: var(--a8c-calendar-button-width);
	height: var(--a8c-calendar-button-height);

	border: none;
	border-radius: variables.$radius-small;

	font: inherit;
	font-variant-numeric: tabular-nums;
	color: inherit;

	// Use the button's ::before to render date's background, which keeps the
	// border-radius of the button intact. This technique allows the focus ring
	// to have rounded corners even when the background needs square corners
	// (eg. in the middle of a date range).
	&::before {
		content: '';
		position: absolute;
		z-index: -1;
		inset: 0;
		border: none; // No default border to avoid polluting high-contrast mode.
		border-radius: variables.$radius-small;
	}

	// Use the button's ::after to show the selection preview.
	&::after {
		content: '';
		position: absolute;
		z-index: 1;
		inset: 0;
		pointer-events: none;
	}

	&:disabled {
		cursor: revert;

		@media (forced-colors: active) {
		// As an extra visual cue, show a line-through on disabled days
		// in forced-colors (high-contrast) mode.
		text-decoration: line-through;
		}
	}

	&:focus-visible {
		outline: var(--a8c-calendar-outline-focus);
		outline-offset: 1px;
	}
}

.calendar__caption-label {
	z-index: 1;

	position: relative;
	display: inline-flex;
	align-items: center;

	white-space: nowrap;
	border: 0;

	text-transform: capitalize;
}

.calendar__button-next,
.calendar__button-previous {
	border: none;
	border-radius: variables.$radius-small;
	background: none;
	padding: 0;
	margin: 0;
	cursor: pointer;
	-moz-appearance: none;
	-webkit-appearance: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	position: relative;
	appearance: none;

	width: var(--a8c-calendar-button-width);
	height: var(--a8c-calendar-button-height);

	color: inherit;

	&:disabled,
	&[aria-disabled="true"] {
		cursor: revert;

		color: theme.$components-color-disabled;
	}

	&:focus-visible {
		outline: var(--a8c-calendar-outline-focus);
	}
}

.calendar__chevron {
	display: inline-block;
	fill: currentColor;
	width: variables.$grid-unit-20;
	height: variables.$grid-unit-20;
}

.calendar[dir="rtl"] .calendar__nav .calendar__chevron {
	transform: rotate(180deg);
	transform-origin: 50%;
}

.calendar__month-caption {
	display: flex;
	justify-content: center;
	align-content: center;

	height: var(--a8c-calendar-nav-height);
	margin-bottom: variables.$grid-unit-15;
}

.calendar__months {
	position: relative;
	display: flex;
	justify-content: center;
	flex-wrap: wrap;
	gap: variables.$grid-unit-20;
	max-width: fit-content;
}

.calendar__month-grid {
	border-collapse: separate;
	border-spacing: 0 variables.$grid-unit-05;
}

.calendar__nav {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	inset-inline-end: 0;

	display: flex;
	align-items: center;
	justify-content: space-between;

	height: var(--a8c-calendar-nav-height);
}

.calendar__weekday {
	width: var(--a8c-calendar-button-width);
	height: var(--a8c-calendar-button-height);
	padding: 0;

	color: theme.$components-color-gray-700;
	text-align: center;
	text-transform: uppercase;
}

/* DAY MODIFIERS */
// Today's date: show a dot in the top-right corner of the button
.calendar__day--today::after {
	content: '';
	position: absolute;
	z-index: 1;
	inset-block-start: 2px;
	inset-inline-end: 2px;
	width: 0;
	height: 0;
	border-radius: 50%;
	border: 2px solid currentColor;
}

// Selected date button (individual date, range start, and range end)
.calendar__day--selected:not(.calendar__range-middle) {
	&:has(.calendar__day-button, .calendar__day-button:hover:not(:disabled)) {
		color: theme.$components-color-foreground-inverted;
	}

	.calendar__day-button {
		&::before {
			background-color: theme.$components-color-foreground;
			// Render a transparent border to highlight the selected day in
			// forced-colors (high-contrast) mode, since the background is not
			// visible.
			border: 1px solid transparent;
		}

		&:disabled::before {
			background-color: theme.$components-color-disabled;
		}

		&:hover:not(:disabled)::before {
			background-color: theme.$components-color-gray-800;
		}
	}
}

// Hidden button (ie. outside current month but still rendered)
.calendar__day--hidden {
	visibility: hidden;
}

// Range start button, but not when start and end are the same day.
.calendar__range-start:not(.calendar__range-end) .calendar__day-button {
	// Apply border-radius changes to the button itself too, so that the focus
	// ring follows the same shape as the button's background.
	&, &::before {
		border-start-end-radius: 0;
		border-end-end-radius: 0;
	}
}

// Middle of date range
.calendar__range-middle .calendar__day-button {
	&::before {
		background-color: var(--a8c-calendar-range-middle-background-color);
		border-radius: 0;

		// Render a top and bottom transparent border to highlight the selected
		// day in forced-colors (high-contrast) mode, since the background is not
		// visible.
		border-width: 1px 0;
		border-color: transparent;
		border-style: solid;
	}
}

// Range end button, but not when start and end are the same day.
.calendar__range-end:not(.calendar__range-start) .calendar__day-button {
	// Apply border-radius changes to the button itself too, so that the focus
	// ring follows the same shape as the button's background.
	&, &::before {
		border-start-start-radius: 0;
		border-end-start-radius: 0;
	}
}

/*
 * RANGE PREVIEW (range calendar only)
 *
 * The preview is rendered in the button's ::after pseudo-element, so that it
 * can be rendered over the button's contents.
 * The selection preview is shown with a dashed border. In order to have
 * control over the dash pattern (especially the seams between days), the
 * dashed borders are rendered as SVGs via the url() CSS function.
 * Since SVGs rendered in the url() function don't seem to be able to access
 * CSS variables, we're using the SVGs as masks, and using `background-color`
 * to consume the accent color variable.
 */
.calendar__day--preview svg {
	position: absolute;
	inset: 0;
	pointer-events: none;
	color: var(--a8c-calendar-preview-border-color);

	@media (forced-colors: active) {
		color: inherit;
	}

	.calendar[dir="rtl"] & {
		transform: scaleX(-1);
	}
}

.calendar__day--preview.calendar__range-middle .calendar__day-button::before {
	// Remove the transparent border shown on the middle of the range
	// in forced-colors (high-contrast) mode, to allow for the dashed border
	// to be visible.
	border: none;
}

/* ANIMATIONS */
@keyframes slide-in-left {
	0% {
		transform: translateX(-100%);
	}
	100% {
		transform: translateX(0);
	}
}

@keyframes slide-in-right {
	0% {
		transform: translateX(100%);
	}
	100% {
		transform: translateX(0);
	}
}

@keyframes slide-out-left {
	0% {
		transform: translateX(0);
	}
	100% {
		transform: translateX(-100%);
	}
}

@keyframes slide-out-right {
	0% {
		transform: translateX(0);
	}
	100% {
		transform: translateX(100%);
	}
}

@keyframes fade-in {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@keyframes fade-out {
	from {
		opacity: 1;
	}
	to {
		opacity: 0;
	}
}

.calendar__weeks-before-enter,
.calendar__weeks-before-exit,
.calendar__weeks-after-enter,
.calendar__weeks-after-exit,
.calendar__caption-after-enter,
.calendar__caption-after-exit,
.calendar__caption-before-enter,
.calendar__caption-before-exit {
	animation-duration: 0s;
	animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	animation-fill-mode: forwards;

	@media not (prefers-reduced-motion) {
		animation-duration: 0.3s;
	};
}

.calendar__weeks-before-enter,
.calendar[dir="rtl"] .calendar__weeks-after-enter {
  	animation-name: slide-in-left;
}
.calendar__weeks-before-exit,
.calendar[dir="rtl"] .calendar__weeks-after-exit {
  	animation-name: slide-out-left;
}
.calendar__weeks-after-enter,
.calendar[dir="rtl"] .calendar__weeks-before-enter {
  	animation-name: slide-in-right;
}
.calendar__weeks-after-exit,
.calendar[dir="rtl"] .calendar__weeks-before-exit {
  	animation-name: slide-out-right;
}

.calendar__caption-after-enter {
  	animation-name: fade-in;
}
.calendar__caption-after-exit {
  	animation-name: fade-out;
}
.calendar__caption-before-enter {
  	animation-name: fade-in;
}
.calendar__caption-before-exit {
  	animation-name: fade-out;
}
